package personnel.department.pages;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import com.google.common.collect.Lists;

import personnel.department.dao.entity.Employee;
import personnel.department.dao.entity.UniqueObject;
import personnel.department.pages.addpage.AddPersonalPage;

public abstract class PDTable<T extends UniqueObject> {

	private final TableViewer viewer;
	private final Composite parent;
	private Table table;
	
	public PDTable(Composite parent) {
		this.parent = parent;
		this.viewer = new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
	}

	public void createTable() {
		createColumns(parent, getViewer());
		table = getViewer().getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		getViewer().setContentProvider(new ArrayContentProvider());
		// get the content for the viewer, setInput will call getElements in the
		// contentProvider
		getViewer().setInput(setModelProvider());
		// make the selection available to other views
		//	    getSite().setSelectionProvider(viewer);
		// set the sorter for the table

		// define layout for the viewer
		GridData gridData = getTableGridData();
		getViewer().getControl().setLayoutData(gridData);
	}

	private GridData getTableGridData() {
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		return gridData;
	}

	public abstract List<T> setModelProvider();
	
	@SuppressWarnings("unchecked")
	public List<T> getModelProvider() {
		return (List<T>) getViewer().getInput();
	}
	
	public void clear() {
		List<T> modelProvider = getModelProvider();
		modelProvider.clear();
		getViewer().setInput(modelProvider);
	}
	
	public void addElement(T element) {
		List<T> modelProvider = getModelProvider();
		modelProvider.add(element);
		getViewer().setInput(modelProvider);
	}
	
	public void addElements(List<T> elements) {
		List<T> modelProvider = getModelProvider();
		modelProvider.addAll(elements);
		getViewer().setInput(modelProvider);
	}

	protected abstract void createColumns(Composite parent, TableViewer viewer);

	public TableViewer getViewer() {
		return viewer;
	}
	
	public void setOpenAction() {
		viewer.addDoubleClickListener(event -> {
			IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
			Employee currentEmployee = (Employee) selection.getFirstElement();
			new AddPersonalPage(currentEmployee).createContent();				
		});
	}
	
	public void setSelectionAction(ISelectionChangedListener listener) {
		viewer.addSelectionChangedListener(listener);
	}
	
	public String getDataToCsv() {
		StringBuilder b = new StringBuilder();
		List<Integer> visibleIndex = Lists.newArrayList();
		appendColumnHeader(b, visibleIndex);
		appendTableItem(b, visibleIndex);
		return b.toString();
	}

	private void appendTableItem(StringBuilder b, List<Integer> visibleIndex) {
		TableItem[] items = table.getItems();
		for (TableItem tableItem : items) {
			for (Integer index: visibleIndex) {
				b.append(tableItem.getText(index));
				b.append(";");
			}
			b.append("\n");
		}
	}

	private void appendColumnHeader(StringBuilder b, List<Integer> visibleIndex) {
		TableColumn[] columns = table.getColumns();
		for (int i = 0; i < columns.length; i++) {
			TableColumn tableColumn = columns[i];
			if (tableColumn.getWidth() > 0) {
				visibleIndex.add(i);
				b.append(tableColumn.getText());
				b.append(";");
			}
		}
		b.append("\n");
	}
}
